package com.lambkit.module.upms.auth.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.lambkit.auth.AuthConfig;
import com.lambkit.auth.AuthEntity;
import com.lambkit.auth.AuthUser;
import com.lambkit.auth.cache.IUserCache;
import com.lambkit.auth.service.AuthDataService;
import com.lambkit.core.Lambkit;
import com.lambkit.module.upms.UpmsApiService;
import com.lambkit.module.upms.UpmsConfig;
import com.lambkit.module.upms.auth.cache.UpmsCache;
import com.lambkit.module.upms.row.UpmsPermission;
import com.lambkit.module.upms.row.UpmsRole;
import com.lambkit.module.upms.row.UpmsUser;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author yangyong(孤竹行)
 */
public class UpmsDataService implements AuthDataService {

    private UpmsCache cache;
    @Override
    public IUserCache getCache() {
        if(cache==null) {
            cache = Lambkit.get(UpmsCache.class);
        }
        return cache;
    }

    @Override
    public String getPasswordSecurity(String username, String password) {
        UpmsUser user = Lambkit.get(UpmsApiService.class).selectUpmsUserByUsername(username);
        if(user!=null && StrUtil.isNotBlank(password)) {
            return encrypt(password, user.getSalt());
        }
        return null;
    }

    public boolean rexCheckPassword(String input) {
        // 6-32 位，字母、数字、字符
        String regStr = Lambkit.config("auth.password.regex", "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_]+$)(?![a-z0-9]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{6,32}$");
        return input.matches(regStr);
    }

    public String encrypt(String password, String salt) {
        UpmsConfig config = Lambkit.config(UpmsConfig.class);
        return encrypt(password, salt, config.getPasswordEncrypt());
    }

    public String encrypt(String password, String salt, String type) {
        String passwordAndsalt = password + salt;
        if("sha".equals(type)) {
            return SecureUtil.sha256(passwordAndsalt);
        } else if("md5".equals(type)) {
            return SecureUtil.md5(passwordAndsalt);
        } else if("hmacSha".equals(type)) {
            return SecureUtil.hmacSha256(salt).digestHex(password);
        } else if("hmacmd5".equals(type)) {
            return SecureUtil.hmacMd5(salt).digestHex(password);
        }
        return SecureUtil.md5(passwordAndsalt);
    }

    @Override
    public AuthUser getAuthUser(String userName) {
        UpmsUser upmsUser = Lambkit.get(UpmsApiService.class).selectUpmsUserByUsername(userName);
        return getAuthUser(upmsUser);
    }
    public AuthUser getAuthUser(UpmsUser upmsUser) {
        AuthUser authUser = new AuthUser();
        authUser.setUserCode(upmsUser.getUsername());
        authUser.setUserId(upmsUser.getUserId());
        authUser.setUserName(upmsUser.getUsername());
        authUser.setRealName(upmsUser.getRealname());
        authUser.setUserBean(upmsUser);
        authUser.setType("normal");
        return authUser;
    }

    @Override
    public AuthEntity getAuthEntity(String userName) {
        UpmsUser upmsUser = Lambkit.get(UpmsApiService.class).selectUpmsUserByUsername(userName);
        return getAuthEntity(upmsUser);
    }

    public AuthEntity getAuthEntity(UpmsUser upmsUser) {
        AuthEntity authEntity = new AuthEntity();

        AuthUser authUser = new AuthUser();
        authUser.setUserCode(upmsUser.getUsername());
        authUser.setUserId(upmsUser.getUserId());
        authUser.setUserName(upmsUser.getUsername());
        authUser.setRealName(upmsUser.getRealname());
        authUser.setUserBean(upmsUser);
        authUser.setType("normal");

        //authEntity
        authEntity.setAuthUser(authUser);
        authEntity.setLoginTime(DateUtil.current());
        AuthConfig authConfig = Lambkit.config(AuthConfig.class);
        authEntity.setExpireTime(authEntity.getLoginTime() + authConfig.getLoginExpirationSecond() * 1000);

        boolean superRole = false;
        // 当前用户所有角色
        List<UpmsRole> upmsRoles = Lambkit.get(UpmsApiService.class).selectUpmsRoleByUpmsUserId(upmsUser.getUserId());
        if(upmsRoles!=null) {
            Set<String> roles = new HashSet<>();
            for (UpmsRole upmsRole : upmsRoles) {
                if (StrUtil.isNotBlank(upmsRole.getName())) {
                    roles.add(upmsRole.getName());
                    if("super".equals(upmsRole.getName())) {
                        superRole = true;
                        authUser.setType("super");
                    }
                }
            }
            authEntity.setRoles(roles);
        }

        if(superRole) {
            //超级管理员 始终拥有所有权限
            Set<String> permissions = new HashSet<>();
            permissions.add("*");
            authEntity.setPermissions(permissions);
        } else {
            // 当前用户所有权限
            List<UpmsPermission> upmsPermissions = Lambkit.get(UpmsApiService.class).selectUpmsPermissionByUpmsUserId(authUser.getUserId());
            if(upmsPermissions!=null) {
                Set<String> permissions = new HashSet<>();
                for (UpmsPermission upmsPermission : upmsPermissions) {
                    if (StrUtil.isNotBlank(upmsPermission.getPermissionValue())) {
                        permissions.add(upmsPermission.getPermissionValue());
                        //permissions.add(upmsPermission.getUri());
                    }
                }
                authEntity.setPermissions(permissions);
            }
        }
        return authEntity;
    }

    @Override
    public List<?> getRoles(Object userid) {
        if(userid!=null) {
            return Lambkit.get(UpmsApiService.class).selectUpmsRoleByUpmsUserId(Long.valueOf(userid.toString()));
        }
        return null;
    }

    @Override
    public List<?> getRules(Object userid) {
        if(userid!=null) {
            return Lambkit.get(UpmsApiService.class).selectUpmsPermissionByUpmsUserId(Long.valueOf(userid.toString()));
        }
        return null;
    }

    public Boolean hasRole(Long userId, Long roleId) {
        // TODO Auto-generated method stub
        return Lambkit.get(UpmsApiService.class).hasRole(userId, roleId);
    }

    public Boolean hasRole(Long userId, String roleName) {
        // TODO Auto-generated method stub
        return Lambkit.get(UpmsApiService.class).hasRole(userId, roleName);
    }

    public Boolean lacksRole(String roleName) {
        // TODO Auto-generated method stub
        return Lambkit.get(UpmsApiService.class).lacksRole(roleName);
    }

    public Boolean hasAnyRoles(Long userId, String roleNames) {
        // TODO Auto-generated method stub
        return Lambkit.get(UpmsApiService.class).hasAnyRoles(userId, roleNames);
    }

    public Boolean hasAllRoles(Long userId, String roleNames) {
        // TODO Auto-generated method stub
        return Lambkit.get(UpmsApiService.class).hasAllRoles(userId, roleNames);
    }

    public Boolean hasRule(Long userId, Long ruleId) {
        // TODO Auto-generated method stub
        return Lambkit.get(UpmsApiService.class).hasRule(userId, ruleId);
    }

    public Boolean hasRule(Long userId, String permission) {
        // TODO Auto-generated method stub
        return Lambkit.get(UpmsApiService.class).hasRule(userId, permission);
    }

    public Boolean lacksRule(String permission) {
        // TODO Auto-generated method stub
        return Lambkit.get(UpmsApiService.class).lacksRule(permission);
    }

    public Boolean hasAnyRules(Long userId, String permissions) {
        // TODO Auto-generated method stub
        return Lambkit.get(UpmsApiService.class).hasAnyRules(userId, permissions);
    }

    public Boolean hasAllRules(Long userId, String permissions) {
        // TODO Auto-generated method stub
        return Lambkit.get(UpmsApiService.class).hasAllRules(userId, permissions);
    }
}
